<template>
  <div class="form-item" :class="{ 'has-error': errors.length > 0 }">
    <label v-if="field.label" :for="field.name">
      {{ field.label }}
      <span v-if="field.required" class="required-asterisk">*</span>
    </label>

    <!-- 输入框 -->
    <input v-if="field.type === 'input'" :id="field.name" v-model="modelValue" :type="field.props?.type || 'text'"
      :placeholder="field.placeholder" :disabled="field.disabled" :name="field.name" @blur="handleBlur"
      v-bind="field.props" />

    <!-- 文本域 -->
    <textarea v-else-if="field.type === 'textarea'" :id="field.name" v-model="textareaValue"
      :placeholder="field.placeholder" :disabled="field.disabled" :name="field.name" @blur="handleBlur"
      v-bind="field.props"></textarea>

    <!-- 下拉选择 -->
    <select v-else-if="field.type === 'select'" :id="field.name" v-model="modelValue" :disabled="field.disabled"
      :name="field.name" @blur="handleBlur" v-bind="field.props">
      <option v-if="field.placeholder" value="" disabled hidden>
        {{ field.placeholder }}
      </option>
      <option v-for="option in field.options" :key="option.value" :value="option.value" :disabled="option.disabled">
        {{ option.label }}
      </option>
    </select>

    <!-- 单选按钮组 -->
    <div v-else-if="field.type === 'radio'" class="radio-group">
      <div v-for="option in field.options" :key="option.value" class="radio-option">
        <input type="radio" :id="`${field.name}-${option.value}`" v-model="modelValue" :value="option.value"
          :disabled="field.disabled || option.disabled" :name="field.name" @blur="handleBlur" v-bind="field.props" />
        <label :for="`${field.name}-${option.value}`">{{ option.label }}</label>
      </div>
    </div>

    <!-- 复选框组 -->
    <div v-else-if="field.type === 'checkbox' && field.options" class="checkbox-group">
      <div v-for="option in field.options" :key="option.value" class="checkbox-option">
        <input type="checkbox" :id="`${field.name}-${option.value}`" v-model="modelValue" :value="option.value"
          :disabled="field.disabled || option.disabled" @blur="handleBlur" v-bind="field.props" />
        <label :for="`${field.name}-${option.value}`">{{ option.label }}</label>
      </div>
    </div>

    <!-- 单个复选框 -->
    <div v-else-if="field.type === 'checkbox' && !field.options" class="single-checkbox">
      <input type="checkbox" :id="field.name" v-model="modelValue" :disabled="field.disabled" :name="field.name"
        @blur="handleBlur" v-bind="field.props" />
      <label :for="field.name">{{ field.label }}</label>
    </div>

    <!-- 日期选择 -->
    <input v-else-if="field.type === 'date'" :id="field.name" v-model="modelValue" type="date"
      :placeholder="field.placeholder" :disabled="field.disabled" :name="field.name" @blur="handleBlur"
      v-bind="field.props" />

    <!-- 开关 -->
    <div v-else-if="field.type === 'switch'" class="switch-container">
      <label class="switch">
        <input type="checkbox" :id="field.name" v-model="modelValue" :disabled="field.disabled" :name="field.name"
          @blur="handleBlur" v-bind="field.props" />
        <span class="slider round"></span>
      </label>
      <span class="switch-label">{{ field.label }}</span>
    </div>

    <!-- 滑块 -->
    <div v-else-if="field.type === 'slider'" class="slider-container">
      <input type="range" :id="field.name" v-model="modelValue" :min="field.props?.min || 0"
        :max="field.props?.max || 100" :step="field.props?.step || 1" :disabled="field.disabled" :name="field.name"
        @blur="handleBlur" v-bind="field.props" />
      <span class="slider-value">{{ modelValue }}</span>
    </div>

    <!-- 错误信息 -->
    <div v-if="errors.length > 0" class="error-messages">
      <span v-for="(error, index) in errors" :key="index" class="error-message">
        {{ error }}
      </span>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue';
import type { FormField } from '../../types/dynamicForm';

export default defineComponent({
  name: 'DynamicFormItem',
  props: {
    field: {
      type: Object as () => FormField,
      required: true
    },
    modelValue: {
      type: [String, Number, Boolean, Array, Date],
      default: ''
    },
    errors: {
      type: Array as () => string[],
      default: () => []
    }
  },
  emits: ['update:modelValue', 'validate'],
  setup(props, { emit }) {
    const modelValue = computed({
      get: () => props.modelValue,
      set: (value) => emit('update:modelValue', value)
    });

    // Ensure textarea value is always string or null
    const textareaValue = computed({
      get: () => {
        if (typeof modelValue.value === 'string' || typeof modelValue.value === 'number' || modelValue.value == null) {
          return modelValue.value;
        }
        return modelValue.value?.toString?.() ?? '';
      },
      set: (val) => {
        emit('update:modelValue', val);
      }
    });

    const handleBlur = () => {
      emit('validate', props.field.name);
    };

    return {
      modelValue,
      textareaValue,
      handleBlur
    };
  }
});
</script>

<style scoped>
.form-item {
  margin-bottom: 20px;
}

.form-item label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
  color: #333;
}

.required-asterisk {
  color: #f44336;
  margin-left: 4px;
}

input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
textarea,
select {
  width: 100%;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
  transition: border-color 0.3s;
}

input[type="text"]:focus,
input[type="password"]:focus,
input[type="email"]:focus,
input[type="number"]:focus,
input[type="date"]:focus,
textarea:focus,
select:focus {
  border-color: #4CAF50;
  outline: none;
}

textarea {
  min-height: 100px;
  resize: vertical;
}

.radio-group,
.checkbox-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.radio-option,
.checkbox-option,
.single-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
}

.single-checkbox label {
  margin-bottom: 0;
}

.switch-container {
  display: flex;
  align-items: center;
  gap: 10px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  transition: .4s;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: .4s;
}

input:checked+.slider {
  background-color: #4CAF50;
}

input:focus+.slider {
  box-shadow: 0 0 1px #4CAF50;
}

input:checked+.slider:before {
  transform: translateX(26px);
}

.slider.round {
  border-radius: 34px;
}

.slider.round:before {
  border-radius: 50%;
}

.switch-label {
  font-weight: normal;
}

.slider-container {
  display: flex;
  align-items: center;
  gap: 10px;
}

.slider-container input[type="range"] {
  flex-grow: 1;
}

.slider-value {
  min-width: 30px;
  text-align: center;
}

.error-messages {
  margin-top: 5px;
}

.error-message {
  display: block;
  color: #f44336;
  font-size: 14px;
}

.has-error input,
.has-error textarea,
.has-error select {
  border-color: #f44336;
}
</style>